<template>
  <div id="relationChart" style="width: 500px; height: 500px;"></div>
</template>

<script setup>
import * as echarts from 'echarts';
import { markRaw, watch } from 'vue'
import { ref, onMounted } from 'vue'
import lodash from 'lodash' 

const props = defineProps({
  labels: {
    type: Array,
    required: true
  },
  relations: {
    type: Array,
    required: true
  },
  filterMin: {
    type: Number,
    required: true
  }
});
const updateChartOnPropsChange = () => {
  updateChart(props.labels, props.relations)
}
watch([()=>props.labels, ()=>props.relations, ()=>props.filterMin], ()=>{
  updateChartOnPropsChange()
})
const chart = ref(null)
const initChart = () => {
  const dom = document.getElementById('relationChart')
  chart.value = markRaw(echarts.init(dom));
}
const dataMax = (data) => {
  const arr = data.flat()
  return Math.max(...arr)
}
const convertData = (labels, data) => {
  let nodes = []
  let links = []
  const transposedData = lodash.zip(...data)
  const maxValue = Math.max(...data.flat())

  // 每个节点被注意的程度是从别的节点来的，所以要按列求和
  for (let i = 0; i < labels.length; i++) {
    const nodeValue = transposedData[i].reduce((a, b) => a + b, 0)
    nodes.push({
      name: i,
      label: {show: true, formatter: ()=>`${labels[i]}`},
      value: nodeValue,
      symbolSize: Math.max(5, nodeValue*20),
      tooltip: {
        formatter: (params) => ('总注意力：' + params.value.toFixed(3))
      }
    })
    for (let j = 0; j < labels.length; j++) {
      if (data[i][j] > 0 && data[i][j] >= props.filterMin) {
        links.push({
          source: i,
          target: j,
          value: data[i][j],
          lineStyle: {
            curveness: i > j ? 0.2 : 0.4,
            // color: i > j ? '#7373B9' : '#9F4D95'
            color: lineColorMap[parseInt(data[i][j]/maxValue*100)]  // 关系图连线一直找不到方法使用visualMap。只好自己计算颜色映射。
          }
        })
      }
    }
  }
  return {
    nodes: nodes,
    links: links
  }
}

function splitColors(startColor, endColor) {
  // 将16进制颜色转换为RGB格式
  function hexToRgb(hex) {
    var r = parseInt(hex.substring(1, 3), 16);
    var g = parseInt(hex.substring(3, 5), 16);
    var b = parseInt(hex.substring(5, 7), 16);
    return [r, g, b];
  }
  // 将RGB颜色转换为16进制格式
  function rgbToHex(rgb) {
    var r = parseInt(rgb[0]).toString(16).padStart(2, '0');
    var g = parseInt(rgb[1]).toString(16).padStart(2, '0');
    var b = parseInt(rgb[2]).toString(16).padStart(2, '0');
    return '#' + r + g + b;
  }
  // 将颜色值分成100份
  function splitValue(start, end, count) {
    var step = (end - start) / count;
    var result = [];
    for (var i = 0; i < count; i++) {
      result.push(start + step * i);
    }
    return result;
  }
  // 将颜色分成100份
  var startRgb = hexToRgb(startColor);
  var endRgb = hexToRgb(endColor);
  var rValues = splitValue(startRgb[0], endRgb[0], 100);
  var gValues = splitValue(startRgb[1], endRgb[1], 100);
  var bValues = splitValue(startRgb[2], endRgb[2], 100);
  // 将RGB颜色转换为16进制格式
  var result = [];
  for (var i = 0; i < 100; i++) {
    var rgb = [rValues[i], gValues[i], bValues[i]];
    result.push(rgbToHex(rgb));
  }
  return result;
}
const lineColorMap = splitColors('#00BFFF', '#FF0000')
// console.log('lineColorMap', lineColorMap)

const updateChart = (labels, data) => {
  const option = {
    title: {
      text: '自注意力关系图',
      left: 'center'
    },
    tooltip: {
      formatter: '{c}',
    },
    // visualMap: {
    //   type: 'continuous',
    //   min: 0,
    //   max: 1,
    //   inRange: {
    //     color: ['#00BFFF', '#FF0000']
    //   }
    // },
    series: [
      {
        type: 'graph',
        layout: 'circular',
        circular: {
          rotateLabel: true,
          minAngle: 20,
          sort: 'ascending'
        },
        data: convertData(labels, data).nodes,
        links: convertData(labels, data).links,
        label: {
          show: true,
          position: 'inside',
          formatter: '{b}',
          fontSize: 12
        },
        edgeSymbol: ['none', 'arrow'],
        // edgeSymbolSize: 10,
        lineStyle: {
          width: 1, // (params) => params.data.value / dataMax(data) * 10
          // color: 'source',
          // curveness: 0.2,
          arrowSize: 2,
          arrow: true,
        },
        emphasis: {
          focus: 'adjacency',
          lineStyle: {
            color: '#ff0000',
            width: 5,
            arrowSize: 10,
            arrow: true
          }
        }
      }
    ]
  };
  // console.log('option', option)
  chart.value.setOption(option);
}
onMounted(() => {
  initChart()
  updateChartOnPropsChange()
});
</script>